/**
 * @method useEventEmitter 事件监听发射器
 * @return {UseEventEmitter.EventEmitter} 返回一组事件绑定的函数
 * @property addListener {Function} 添加特定事件监听器
 * @property removeListener {Function} 移除事件监听器
 * @property emit {Function} 触发特定事件，并依次调用与该事件关联的所有监听器函数
 * @property addOnceListener {Function} 添加一次特定事件监听器
 * @property removeAllListeners {Function} 移除所有特定事件监听器
 * @property getListeners {Function} 获取所有特定事件监听器
 * */
const useEventEmitter = (): UseEventEmitter.EventEmitter => {
    let events: UseEventEmitter.Events = {};

    return {
        /**
         * @method addListener 添加特定事件监听器
         * @param eventName {String} 事件名
         * @param listener {UseEventEmitter.Listener} 监听函数
         * */
        addListener(eventName: string, listener: UseEventEmitter.Listener): void {
            if (!events[eventName]) {
                events[eventName] = [];
            }
            events[eventName].push(listener);
        },
        /**
         * @method addOnceListener 添加一次特定事件监听器
         * @param eventName {String} 事件名
         * @param listener {Function} 监听函数
         * */
        addOnceListener(eventName: string, listener: UseEventEmitter.Listener): void {
            const onceListener = (...args: []): void => {
                this.removeListener(eventName, onceListener);
                listener.apply(null, args);
            };
            if (!events[eventName]) {
                events[eventName] = [];
            }
            events[eventName].push(onceListener);
        },
        /**
         * @method removeListener 移除事件监听器
         * @param eventName {String} 事件名
         * @param listener {Function} 事件监听器函数
         * */
        removeListener(eventName: string, listener: UseEventEmitter.Listener): void {
            const eventCallbacks: UseEventEmitter.Events[string] = events[eventName];
            if (eventCallbacks) {
                events[eventName] = events[eventName].filter(
                    (eventListener:UseEventEmitter.Listener):boolean => eventListener !== listener
                );
            }
        },
        /**
         * @method emit 触发特定事件，并依次调用与该事件关联的所有监听器函数
         * @param eventName {String} 事件名
         * @param args 传给监听事件的参数
         * */
        emit(eventName: string, ...args: []): void {
            const eventCallbacks: UseEventEmitter.Events[string] = events[eventName];
            if (eventCallbacks) {
                eventCallbacks.forEach((callback: UseEventEmitter.Listener): void => {
                    callback.apply(null, args);
                });
            }
        },
        /**
         * @method removeAllListeners 移除所有特定事件监听器
         * @param eventName {String} 事件名
         * */
        removeAllListeners(eventName: string): void {
            const eventCallbacks: UseEventEmitter.Events[string] = events[eventName];
            if (eventCallbacks) {
                delete events[eventName];
            }
        },
        /**
         * @method getListeners 获取所有特定事件监听器
         * @param eventName {UseEventEmitter.Events[string]} 事件名
         * */
        getListeners(eventName:string):UseEventEmitter.Events[string] {
            return events[eventName] || [];
        }
    }
};

export default useEventEmitter